package com.heartunderblade.rpc.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import com.heartunderblade.rpc.config.RpcConfig;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Map;

public class ConfigUtilsPlus {
    /**
     * 加载配置对象,前缀prefix
     * @param tClass
     * @param prefix
     * @return
     * @param <T>
     */
    public static <T> T loadConfig(Class<T> tClass,String prefix) {
        return  loadConfig(tClass,prefix,"");
    }

    /**
     *加载配置对象，支持 `.properties`, `.yml`, `.yaml` 文件
     * @param tClass 加载的配置类
     * @param prefix 读取的文件前缀，例如rpc.name。那么prefix就是rpc
     * @param environment 比如namefile-dev
     * @return
     * @param <T>
     */
    public static <T> T loadConfig(Class<T> tClass,String prefix,String environment) {
        //读取applicaiton文件。
        StringBuilder configFileBuilder  = new StringBuilder("application");
        String fullConfigName = getFullConfigName(configFileBuilder.toString(),prefix);
        //application.properties文件
        if(fullConfigName.endsWith("properties")){
            Props props = new Props(fullConfigName);
            return props.toBean(tClass,prefix);
        }
        //yaml或者yml文件
        Yaml yaml = new Yaml();
            InputStream inputStream = ConfigUtilsPlus.class.getClassLoader().getResourceAsStream(fullConfigName);
            Object load = yaml.load(inputStream);
            if(load instanceof Map){
                Map<String, Object> dataMap = (Map<String, Object>) load;
                // 首先检查外层是否有"rpc"键，并确认其值也是一个 Map
                if (dataMap.containsKey(prefix) && dataMap.get(prefix) instanceof Map) {
                    Map<String, Object> innerMap = (Map<String, Object>) dataMap.get(prefix);
                    System.out.println();
                    innerMap.get("name").toString();
                    // 检查内层 Map 是否包含所有指定的键
                    //依次映射至RpcConfig
                    RpcConfig rpcConfig = new RpcConfig();

                    rpcConfig.setHost((String) innerMap.get("host"));
                    rpcConfig.setName((String) innerMap.get("name"));
                    rpcConfig.setServerPort((Integer) innerMap.get("serverPort"));
                    rpcConfig.setSerializer((String) innerMap.get("serializer"));
                    rpcConfig.setLoadBalancer((String) innerMap.get("loadBalancer"));
                    rpcConfig.setRetryStrategy((String) innerMap.get("retryStrategy"));
                    rpcConfig.setTolerantStrategy((String) innerMap.get("tolerantStrategy"));
                    //完成版本号bug，有小数点会被解析为double类型
                    rpcConfig.setVersion(innerMap.get("version") != null ? innerMap.get("version").toString() : null);
                    System.out.println(rpcConfig);

                    return (T) rpcConfig;
                }


            }



        //判断环境为不为空，不为空则加上-后缀
        if(StrUtil.isNotBlank(environment)){
            configFileBuilder.append("-").append(environment);
        }

        //那么就手动加properties
        configFileBuilder.append(".properties");
        Props props = new Props(configFileBuilder.toString());
        return props.toBean(tClass,prefix);
    }

    //判断文件后缀

    /**
     * 判断完整的配置文件名，调用isConfigFileContain判断是否有serverPort，version,name
     * @param configName 传入"application"
     * @param prefix 获取的rpc
     * @return
     */
    private static String getFullConfigName(String configName,String prefix){
        StringBuilder sb  = new StringBuilder(configName);
        sb.append(".yaml");
        Boolean isYaml = isConfigFileContain(sb.toString(),prefix);
        if(isYaml){
            return sb.toString();
        }
        sb = new StringBuilder(configName);
        sb.append(".yml");
        Boolean isYml = isConfigFileContain(sb.toString(),prefix);
        if(isYml){
            return sb.toString();
        }
        return "application.properties";
    }

    /**
     * 判断此文件是否有serverPort，version,name
     * @param FullConfigFileName
     * @param prefix
     * @return
     */
    private static Boolean isConfigFileContain(String FullConfigFileName , String prefix){
        Yaml yaml = new Yaml();
            //判断文件内容是否有rpc.name之类的属性
        try {
            InputStream inputStream = ConfigUtilsPlus.class.getClassLoader().getResourceAsStream(FullConfigFileName);
            Object obj = yaml.load(inputStream);
            // 使用映射方式加载YAML配置为对象
            if(obj instanceof Map){
                Map<String, Object> dataMap = (Map<String, Object>) obj;
                // 首先检查外层是否有"rpc"键，并确认其值也是一个 Map
                if (dataMap.containsKey(prefix) && dataMap.get(prefix) instanceof Map) {
                    Map<String, Object> innerMap = (Map<String, Object>) dataMap.get(prefix);

                    // 检查内层 Map 是否包含所有指定的键
                    if(innerMap != null){
                        return true;
                    }
                }

            }
        } catch (Exception e) {
            System.out.println("文件类型不是 " + FullConfigFileName);
        }

        return false;

    }



}
